home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FM Towns: Free Software Collection 7
/
FM Towns Free Software Collection 7.iso
/
taropyon
/
zmodem
/
src
/
sz.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-11-30
|
45KB
|
2,123 lines
#define __TOWNS__
//#define DEBUG
#define VERSION "3.11 02-26-91"
#define PUBDIR "/usr/spool/uucppublic"
#ifdef __TOWNS__
# define TXBSIZE 16384
# define READCHECK
#endif
/*% cc -compat -M2 -Ox -K -i -DTXBSIZE=16384 -DNFGVMIN -DREADCHECK sz.c -lx -o sz; size sz
<-xtx-*> cc -Osal -DTXBSIZE=32768 -DSV sz.c -lx -o $B/sz; size $B/sz
****************************************************************************
*
* sz.c By Chuck Forsberg, Omen Technology INC
*
****************************************************************************
*
* Typical Unix/Xenix/Clone compiles:
*
* cc -O sz.c -o sz USG (SYS III/V) Unix
* cc -O -DSV sz.c -o sz Sys V Release 2 with non-blocking input
* Define to allow reverse channel checking
* cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
*
* cc -O -K -i -DNFGVMIN -DREADCHECK sz.c -lx -o sz Classic Xenix
*
* ln sz sb **** All versions ****
* ln sz sx **** All versions ****
*
****************************************************************************
****************************************************************************
*
*
* A program for Unix to send files and commands to computers running
* Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
*
* Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
*
* USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
*
*
* This version implements numerous enhancements including ZMODEM
* Run Length Encoding and variable length headers. These
* features were not funded by the original Telenet development
* contract.
*
* This software may be freely used for non commercial and
* educational (didactic only) purposes. This software may also
* be freely used to support file transfer operations to or from
* licensed Omen Technology products. Any programs which use
* part or all of this software must be provided in source form
* with this notice intact except by written permission from Omen
* Technology Incorporated.
*
* Use of this software for commercial or administrative purposes
* except when exclusively limited to interfacing Omen Technology
* products requires a per port license payment of $20.00 US per
* port (less in quantity). Use of this code by inclusion,
* decompilation, reverse engineering or any other means
* constitutes agreement to these conditions and acceptance of
* liability to license the materials and payment of reasonable
* legal costs necessary to enforce this license agreement.
*
*
* Omen Technology Inc FAX: 503-621-3745
* Post Office Box 4681
* Portland OR 97208
*
* This code is made available in the hope it will be useful,
* BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
* DAMAGES OF ANY KIND.
*/
#ifndef __TOWNS__
char *substr(), *getenv();
#endif
#define LOGFILE "/tmp/szlog"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stat.h>
#include <setjmp.h>
#include <ctype.h>
#include <errno.h>
#ifdef __TOWNS__
# include <stdarg.h>
# include <process.h>
# include <time.h>
# include <io.h>
# include <splib.h>
# include <fslib.h>
# include "usrlib.h"
# include "rsctrl.h"
# include "flib.h"
# include "msgdat.h"
# ifdef __HIGHC__
# pragma On(Align_labels);
# endif
extern int RsPort;
# define _FSTAT_IGN
#endif
#include "prot.h"
#include "sz.h"
extern int errno;
#define STATIC static
#define HOWMANY 2
STATIC int Zmodem = 0; /* ZMODEM protocol requested by receiver */
unsigned Baudrate = 4800; /* Default, set by first mode() call */
unsigned Effbaud = 4800;
STATIC unsigned Txwindow; /* Control the size of the transmitted window */
STATIC unsigned Txwspac; /* Spacing between zcrcq requests */
STATIC unsigned Txwcnt; /* Counter used to space ack requests */
STATIC long Lrxpos; /* Receiver's last reported offset */
STATIC int errors;
char endmsg[80] = {0}; /* Possible message to display on exit */
#include "rbsb.c" /* most of the system dependent stuff here */
#include "crctab.c"
STATIC int Filesleft;
STATIC long Totalleft;
/*
* Attention string to be executed by receiver to interrupt streaming data
* when an error is detected. A pause (0336) may be needed before the
* ^C (03) or after it.
*/
#ifdef READCHECK
STATIC char Myattn[] = {0};
#else
# ifdef USG
STATIC char Myattn[] = {03, 0336, 0};
# endif
#endif
FILE *in;
char *infile; /* High C stat() */
#ifdef BADSEEK
STATIC int Canseek = 0; /* 1: Can seek 0: only rewind -1: neither (pipe) */
# ifndef TXBSIZE
# define TXBSIZE 16384 /* Must be power of two, < MAXINT */
# endif
#else
STATIC int Canseek = 1; /* 1: Can seek 0: only rewind -1: neither (pipe) */
#endif
#ifdef TXBSIZE
#define TXBMASK (TXBSIZE-1)
STATIC char Txb[TXBSIZE]; /* Circular buffer for file reads */
STATIC char *txbuf = Txb; /* Pointer to current file segment */
#else
STATIC char txbuf[1024];
#endif
STATIC long vpos = 0; /* Number of bytes read from file */
STATIC char Lastrx;
STATIC char Crcflg;
#ifdef DEBUG
STATIC int Verbose = 5;
#else
STATIC int Verbose = 0;
#endif
STATIC int Modem2 = 0; /* XMODEM Protocol - don't send pathnames */
STATIC int Restricted = 0; /* restricted; no /.. or ../ in filenames */
STATIC int Quiet = 0; /* overrides logic that would otherwise set verbose */
STATIC int Ascii = 0; /* Add CR's for brain damaged programs */
STATIC int Fullname = 0; /* transmit full pathname */
STATIC int Unlinkafter = 0; /* Unlink file after it is sent */
STATIC int Dottoslash = 0; /* Change foo.bar.baz to foo/bar/baz */
STATIC int firstsec;
STATIC int errcnt = 0; /* number of files unreadable */
STATIC int blklen = 128; /* length of transmitted records */
STATIC int Optiong; /* Let it rip no wait for sector ACK's */
STATIC int Eofseen; /* EOF seen on input set by zfilbuf */
STATIC int BEofseen; /* EOF seen on input set by fooseek */
STATIC int Totsecs; /* total number of sectors this file */
STATIC int Filcnt = 0; /* count of number of files opened */
STATIC int Lfseen = 0;
STATIC unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
STATIC int Tframlen = 0; /* Override for tx frame length */
STATIC int blkopt = 0; /* Override value for zmodem blklen */
STATIC int Rxflags = 0;
STATIC long bytcnt;
STATIC int Wantfcs32 = TRUE; /* want to send 32 bit FCS */
STATIC char Lzconv; /* Local ZMODEM file conversion request */
STATIC char Lzmanag; /* Local ZMODEM file management request */
STATIC int Lskipnocor;
STATIC char Lztrans;
STATIC int Command; /* Send a command, then exit. */
STATIC char *Cmdstr; /* Pointer to the command string */
STATIC int Cmdtries = 11;
STATIC int Cmdack1; /* Rx ACKs command, then do it */
STATIC int Exitcode;
STATIC int Test = 0; /* 1= Force receiver to send Attn, etc with qbf.
2= Character transparency test */
STATIC char *qbf = "The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
STATIC long Lastsync = 0; /* Last offset to which we got a ZRPOS */
STATIC int Beenhereb4 = 0; /* How many times we've been ZRPOS'd same place */
STATIC jmp_buf tohere; /* For the interrupt on RX timeout */
STATIC jmp_buf intrjmp; /* For the interrupt on RX CAN */
#ifdef XARGSFILE
static char *mystrsave(char *s)
{
register char *p;
char *malloc();
if (p = malloc(strlen(s) + 1))
{
strcpy(p, s);
return p;
}
USR_fprintf(stderr, "No memory for mystrsave!\n");
EXIT(1);
}
/* Remove (presumably) terminating CR and/or LF from string */
static void uncrlf( register char *s )
{
for (; *s; ++s)
switch (*s)
{
case '\r':
case '\n':
*s = 0;
return;
}
}
#endif
#ifdef __TOWNS__
void (*signal_int_func)(int) = SIG_DFL;
extern int CtrlX;
void signal_func(int level)
{
if ( signal_int_func == SIG_ERR )
{
} else if ( signal_int_func == SIG_DFL )
{
EXIT(3);
} else if ( signal_int_func == SIG_IGN )
{
} else
(signal_int_func)(level);
}
void my_signal( int mode, void (*func)(int) )
{
switch ( mode )
{
case SIGINT:
signal_int_func = func;
break;
}
}
#define SIGNAL(_mode,_func) my_signal(_mode,_func)
/* called by signal interrupt or terminate to clean things up */
void bibi(int n)
{
SIGNAL(SIGINT, SIG_IGN);
canit();
mode(0); /* restore original tty mode */
USR_fprintf(stderr, "sz: caught signal %d; exiting\n", n);
if (n == SIGQUIT)
EXIT(0);
if (n == 99)
USR_fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
cucheck();
EXIT(128 + n);
}
/* Called when ZMODEM gets an interrupt (^X) */
void onintr(int level)
{
SIGNAL(SIGINT, SIG_IGN);
CtrlX = FALSE;
longjmp(intrjmp, -1);
}
#else
/* called by signal interrupt or terminate to clean things up */
void bibi(int n)
{
canit();
mode(0); /* restore original tty mode */
USR_fprintf(stderr, "sz: caught signal %d; exiting\n", n);
if (n == SIGQUIT)
abort();
if (n == 99)
USR_fprintf(stderr, "mode(2) in rbsb.c not implemented!!\n");
cucheck();
EXIT(128 + n);
}
/* Called when ZMODEM gets an interrupt (^X) */
void onintr(void)
{
signal(SIGINT, SIG_IGN);
longjmp(intrjmp, -1);
}
#endif
STATIC int Zctlesc; /* Encode control characters */
STATIC int Nozmodem = 0; /* If invoked as "sb" */
STATIC char *Progname = "sz";
STATIC int Zrwindow = 1400; /* RX window size (controls garbage count) */
#include "zm.c"
#include "zmr.c"
#ifdef XARGSFILE
#define XARGSMAX 256
char *xargv[XARGSMAX + 1];
#endif
void zm_main(int argc, char *argv[])
{
register char *cp;
register npats;
int dm;
char **patts;
// static char xXbuf[BUFSIZ];
#ifndef __TOWNS__
if ((cp = getenv("ZNULLS")) && *cp)
Znulls = atoi(cp);
if ((cp = getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
Restricted = TRUE;
#endif
from_cu();
chkinvok(argv[0]);
Rxtimeout = 600;
npats = 0;
if (argc < 2)
usage();
#ifndef __TOWNS__
setbuf(stdout, xXbuf);
#endif
while ( --argc )
{
cp = *++argv;
if (*cp++ == '-' && *cp)
{
while (*cp)
{
switch (*cp++)
{
case '\\':
*cp = toupper(*cp);
continue;
case '+':
Lzmanag = ZMAPND;
break;
#ifdef CSTOPB
case '2':
Twostop = TRUE;
break;
#endif
case 'a':
Lzconv = ZCNL;
Ascii = TRUE;
break;
case 'b':
Lzconv = ZCBIN;
break;
case 'C':
if (--argc < 1)
{
usage();
}
Cmdtries = atoi(*++argv);
break;
case 'i':
Cmdack1 = ZCACK1;
/* **** FALL THROUGH TO **** */
case 'c':
if (--argc != 1)
{
usage();
}
Command = TRUE;
Cmdstr = *++argv;
break;
case 'd':
++Dottoslash;
/* **** FALL THROUGH TO **** */
case 'f':
Fullname = TRUE;
break;
case 'e':
Zctlesc = 1;
break;
case 'k':
blklen = 1024;
break;
case 'L':
if (--argc < 1)
{
usage();
}
blkopt = atoi(*++argv);
if (blkopt < 24 || blkopt > 1024)
usage();
break;
case 'l':
if (--argc < 1)
{
usage();
}
Tframlen = atoi(*++argv);
if (Tframlen < 32 || Tframlen > 1024)
usage();
break;
case 'N':
Lzmanag = ZMNEWL;
break;
case 'n':
Lzmanag = ZMNEW;
break;
case 'o':
Wantfcs32 = FALSE;
break;
case 'p':
Lzmanag = ZMPROT;
break;
case 'r':
if (Lzconv == ZCRESUM)
Lzmanag = (Lzmanag & ZMMASK) | ZMCRC;
Lzconv = ZCRESUM;
break;
case 'q':
Quiet = TRUE;
Verbose = 0;
break;
case 't':
if (--argc < 1)
{
usage();
}
Rxtimeout = atoi(*++argv);
if (Rxtimeout < 10 || Rxtimeout > 1000)
usage();
break;
case 'T':
if (++Test > 1)
{
vfile("test mode");
chartest(1); /* save old tty stat, set raw mode */
chartest(2); /* set XON/XOFF for sb/sz with ZMODEM or YMODEM-g */
mode(0); /* restore original tty mode */
EXIT(0);
}
break;
case 'u':
++Unlinkafter;
break;
case 'v':
++Verbose;
break;
case 'w':
if (--argc < 1)
{
usage();
}
Txwindow = atoi(*++argv);
if (Txwindow < 256)
Txwindow = 256;
Txwindow = (Txwindow / 64) * 64;
Txwspac = Txwindow / 4;
if (blkopt > Txwspac
|| (!blkopt && Txwspac < 1024))
blkopt = Txwspac;
break;
case 'X':
++Modem2;
break;
case 'Y':
Lskipnocor = TRUE;
/* **** FALLL THROUGH TO **** */
case 'y':
Lzmanag = ZMCLOB;
break;
case 'Z':
case 'z':
Lztrans = ZTRLE;
break;
default:
usage();
}
}
} else if (!npats && argc > 0)
{
if (argv[0][0])
{
npats = argc;
patts = argv;
}
}
}
if (npats < 1 && !Command && !Test)
usage();
#ifndef __TOWNS__
if ( Verbose )
{
if ( freopen(LOGFILE, "a", stderr) == NULL )
{
printf("Can't open log file %s\n", LOGFILE);
EXIT(0200);
}
setbuf(stderr, NULL);
}
#endif
if (Fromcu && !Quiet)
{
if (Verbose == 0)
Verbose = 2;
}
#ifdef __TOWNS__
USR_fprintf(stderr,"\n");
USR_fprintf(stderr,"sz ver.%s for TownsOS", MAIN_VER);
USR_fprintf(stderr," orignal sz %s\n\n", VERSION);
#else
vfile("%s %s for %s\n", Progname, VERSION, OS);
#endif
#ifdef XARGSFILE
vfile("npats=%d *patts=%s", npats, *patts);
if (npats == 1 && !strcmp(XARGSFILE, *patts))
{
infile = XARGSFILE; in = FM_fopen(infile, "rb");
if (!in)
{
USR_printf(stderr, "Can't open / control file!\n");
EXIT(2);
}
for (npats = 0, argv = patts = xargv; npats < XARGSMAX; ++npats, ++argv)
{
if (fgets(txbuf, 1024, in) <= 0)
break;
uncrlf(txbuf);
*argv = mystrsave(txbuf);
}
FM_fclose(in);
}
#endif
mode(1); /* save old tty stat, set raw mode */
#ifdef __TOWNS__
SIGNAL(SIGINT,bibi);
#else
if (signal(SIGINT, bibi) == SIG_IGN)
{
signal(SIGINT, SIG_IGN);
signal(SIGKILL, SIG_IGN);
} else
{
signal(SIGINT, bibi);
signal(SIGKILL, bibi);
}
#ifdef SIGQUIT
if (!Fromcu)
signal(SIGQUIT, SIG_IGN);
#endif
#ifdef SIGTERM
signal(SIGTERM, bibi);
#endif
#endif /* endof ifndef __TOWNS__ */
if (!Modem2)
{
if (!Nozmodem)
{
RS_puts(RsPort,"rz\r");
}
countem(npats, patts);
if (!Nozmodem)
{
stohdr(0L);
if (Command)
Txhdr[ZF0] = ZCOMMAND;
zshhdr(4, ZRQINIT, Txhdr);
}
}
if (Command)
{
if (getzrxinit())
{
Exitcode = 0200;
canit();
} else if (zsendcmd(Cmdstr, 1 + strlen(Cmdstr)))
{
Exitcode = 0200;
canit();
}
} else if (wcsend(npats, patts) == ERROR)
{
Exitcode = 0200;
canit();
}
if ( endmsg[0] )
{
#ifdef DEBUG
USR_printf("\n%s\n", endmsg);
#endif
RS_printf(RsPort,"\r\n%s", endmsg);
}
#ifdef __TOWNS__
USR_fprintf(stderr,"\nrx ver.%s finished.\n",MAIN_VER);
#else
RS_printf(RsPort,"\r\n%s %s finished.\r\n", Progname, VERSION);
#endif
mode(0); /* restore original tty mode */
dm = ((errcnt != 0) | Exitcode);
if (dm)
cucheck();
EXIT(dm);
/* NOTREACHED */
}
static int wcsend(int argc, char *argp[])
{
register n;
Crcflg = FALSE;
firstsec = TRUE;
bytcnt = -1;
if (Nozmodem)
{
RS_puts(RsPort,"Start your YMODEM receive. ");
}
for (n = 0; n < argc; ++n)
{
Totsecs = 0;
if (wcs(argp[n]) == ERROR)
return ERROR;
}
Totsecs = 0;
if (Filcnt == 0)
{ /* bitch if we couldn't open ANY files */
if (!Nozmodem && !Modem2)
{
Command = TRUE;
Cmdstr = "echo \"sz: Can't open any requested files\"";
if (getnak())
{
Exitcode = 0200;
canit();
}
if (!Zmodem)
canit();
else if (zsendcmd(Cmdstr, 1 + strlen(Cmdstr)))
{
Exitcode = 0200;
canit();
}
Exitcode = 1;
return OK;
}
canit();
sprintf(endmsg, "Can't open any requested files");
return ERROR;
}
if (Zmodem)
saybibi();
else if (!Modem2)
wctxpn("");
return OK;
}
static int wcs(char *oname)
{
// register char *p, *q;
struct stat f;
char name[PATHLEN];
strcpy(name, oname);
if (Restricted)
{
/* restrict pathnames to current tree or uucppublic */
if (substr(name, "../")
|| (name[0] == '/' && strncmp(name, PUBDIR, strlen(PUBDIR))) )
{
canit();
sprintf(endmsg, "Security Violation");
return ERROR;
}
}
infile = oname; in = FM_fopen(oname, ROPMODE);
if (in == NULL)
{
++errcnt;
return OK; /* pass over it, there may be others */
}
BEofseen = Eofseen = 0;
vpos = 0;
/* Check for directory or block special files */
#ifdef _FSTAT_IGN
stat(infile, &f);
#else
fstat(fileno(in), &f);
#endif
#ifndef __TOWNS__
{
register c;
c = f.st_mode & S_IFMT;
if (c == S_IFDIR || c == S_IFBLK)
{
FM_fclose(in);
return OK;
}
}
#endif
++Filcnt;
switch (wctxpn(name))
{
case ERROR:
return ERROR;
case ZSKIP:
return OK;
}
if (!Zmodem && wctx(f.st_size) == ERROR)
return ERROR;
if (Unlinkafter)
unlink(oname);
return 0;
}
/*
* generate and transmit pathname block consisting of pathname (null
* terminated), file length, mode time and file mode in octal as provided by
* the Unix fstat call. N.B.: modifies the passed name, may extend it!
*/
static int wctxpn(char *name)
{
register char *p, *q;
char name2[PATHLEN];
struct stat f;
#ifdef __TOWNS__
char tmp[PATHLEN];
FS_dos2unix( tmp, name );
if ( !Fullname && isalpha(tmp[0]) && tmp[1] == ':' )
name = &tmp[2];
else
name = tmp;
#endif
if (Modem2)
{
#ifdef _FSTAT_IGN
if (*name && stat(infile, &f) != -1)
#else
if (*name && fstat(fileno(in), &f) != -1)
#endif
{
USR_fprintf(stderr, "Sending %s, %ld XMODEM blocks. ",
name, (127 + f.st_size) >> 7);
}
USR_fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
return OK;
}
zperr("Awaiting pathname nak for %s", *name ? name : "<END>");
if (!Zmodem)
{
if (getnak())
return ERROR;
}
q = (char *) 0;
if (Dottoslash)
{ /* change . to . */
for (p = name; *p; ++p)
{
if (*p == '/')
q = p;
else if (*p == '.')
*(q = p) = '/';
}
if (q && strlen(++q) > 8)
{ /* If name>8 chars */
q += 8; /* make it .ext */
strcpy(name2, q); /* save excess of name */
*q = '.';
strcpy(++q, name2); /* add it back */
}
}
for (p = name, q = txbuf; *p;)
{
if ((*q++ = *p++) == '/' && !Fullname)
q = txbuf;
}
*q++ = 0;
p = q;
while (q < (txbuf + 1024))
*q++ = 0;
if (*name)
{
#ifdef _FSTAT_IGN
if ( stat(infile, &f) != -1 )
#else
if ( fstat(fileno(in), &f) != -1 )
#endif
sprintf(p, "%lu %lo %o 0 %d %ld", f.st_size, f.st_mtime,
f.st_mode, Filesleft, Totalleft);
USR_fprintf(stderr,"\nSend header : %s\n", p );
Totalleft -= f.st_size;
}
if (--Filesleft <= 0)
Totalleft = 0;
if (Totalleft < 0)
Totalleft = 0;
/* force 1k blocks if name won't fit in 128 byte block */
if (txbuf[125])
blklen = 1024;
else
{ /* A little goodie for IMP/KMD */
txbuf[127] = (f.st_size + 127) >> 7;
txbuf[126] = (f.st_size + 127) >> 15;
}
if (Zmodem)
return zsendfile(txbuf, 1 + strlen(p) + (p - txbuf));
if (wcputsec(txbuf, 0, 128) == ERROR)
return ERROR;
return OK;
}
static int getnak(void)
{
register firstch;
Lastrx = 0;
for (;;)
{
switch (firstch = readline(800))
{
case ZPAD:
if (getzrxinit())
return ERROR;
Ascii = 0; /* Receiver does the conversion */
return FALSE;
case TIMEOUT:
sprintf(endmsg, "Timeout waiting for ZRINIT");
return TRUE;
case WANTG:
#ifdef MODE2OK
mode(2); /* Set cbreak, XON/XOFF, etc. */
/* set XON/XOFF for sb/sz with ZMODEM or YMODEM-g */
#endif
Optiong = TRUE;
blklen = 1024;
case WANTCRC:
Crcflg = TRUE;
case NAK:
return FALSE;
case CAN:
if ((firstch = readline(20)) == CAN && Lastrx == CAN)
{
sprintf(endmsg, "Got CAN waiting to send file");
return TRUE;
}
default:
break;
}
Lastrx = firstch;
}
}
static int wctx(long flen)
{
register int thisblklen;
register int sectnum, attempts, firstch;
long charssent;
charssent = 0;
firstsec = TRUE;
thisblklen = blklen;
vfile("wctx:file length=%ld", flen);
while ((firstch = readline(Rxtimeout)) != NAK && firstch != WANTCRC
&& firstch != WANTG && firstch != TIMEOUT && firstch != CAN)
;
if (firstch == CAN)
{
zperr("Receiver CANcelled");
return ERROR;
}
if (firstch == WANTCRC)
Crcflg = TRUE;
if (firstch == WANTG)
Crcflg = TRUE;
sectnum = 0;
for (;;)
{
if (flen <= (charssent + 896L))
thisblklen = 128;
if (!filbuf(txbuf, thisblklen))
break;
if (wcputsec(txbuf, ++sectnum, thisblklen) == ERROR)
return ERROR;
charssent += thisblklen;
}
FM_fclose(in);
attempts = 0;
do
{
purgeline();
sendline(EOT);
flushmo();
++attempts;
}
while ( ((firstch = (readline(Rxtimeout))) != ACK) && attempts < RETRYMAX);
if (attempts == RETRYMAX)
{
zperr("No ACK on EOT");
return ERROR;
} else
return OK;
}
/* data length of this sector to send */
static int wcputsec(char *buf, int sectnum, int cseclen)
{
register checksum, wcj;
register char *cp;
unsigned oldcrc;
int firstch;
int attempts;
firstch = 0; /* part of logic to detect CAN CAN */
if (Verbose > 2)
USR_fprintf(stderr, "Sector %3d %2dk\n", Totsecs, Totsecs / 8);
else if (Verbose > 1)
USR_fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs / 8);
for (attempts = 0; attempts <= RETRYMAX; attempts++)
{
Lastrx = firstch;
sendline(cseclen == 1024 ? STX : SOH);
sendline(sectnum);
sendline(-sectnum - 1);
oldcrc = checksum = 0;
for (wcj = cseclen, cp = buf; --wcj >= 0;)
{
sendline(*cp);
oldcrc = updcrc((0377 & *cp), oldcrc);
checksum += *cp++;
}
if (Crcflg)
{
oldcrc = updcrc(0, updcrc(0, oldcrc));
sendline((int) oldcrc >> 8);
sendline((int) oldcrc);
} else
sendline(checksum);
flushmo();
if (Optiong)
{
firstsec = FALSE;
return OK;
}
firstch = readline(Rxtimeout);
gotnak:
switch (firstch)
{
case CAN:
if (Lastrx == CAN)
{
cancan:
zperr("Cancelled");
return ERROR;
}
break;
case TIMEOUT:
zperr("Timeout on sector ACK");
continue;
case WANTCRC:
if (firstsec)
Crcflg = TRUE;
case NAK:
zperr("NAK on sector");
continue;
case ACK:
firstsec = FALSE;
Totsecs += (cseclen >> 7);
return OK;
case ERROR:
zperr("Got burst for sector ACK");
break;
default:
zperr("Got %02x for sector ACK", firstch);
break;
}
for (;;)
{
Lastrx = firstch;
if ((firstch = readline(Rxtimeout)) == TIMEOUT)
break;
if (firstch == NAK || firstch == WANTCRC)
goto gotnak;
if (firstch == CAN && Lastrx == CAN)
goto cancan;
}
}
zperr("Retry Count Exceeded");
return ERROR;
}
/* fill buf with count chars padding with ^Z for CPM */
static int filbuf(register char *buf, int count)
{
register c, m;
if (!Ascii)
{
#ifndef __TOWNS__
m = read(fileno(in), buf, count);
#else
m = fread(buf,1,count,in);
#endif
if (m <= 0)
return 0;
while (m < count)
buf[m++] = 032;
return count;
}
m = count;
if (Lfseen)
{
*buf++ = 012;
--m;
Lfseen = 0;
}
while ((c = getc(in)) != EOF)
{
if (c == 012)
{
*buf++ = 015;
if (--m == 0)
{
Lfseen = TRUE;
break;
}
}
*buf++ = c;
if (--m == 0)
break;
}
if (m == count)
return 0;
else
while (--m >= 0)
*buf++ = CPMEOF;
return count;
}
/* Fill buffer with blklen chars */
static int zfilbuf(void)
{
int n;
#ifdef TXBSIZE
vfile("zfilbuf: bytcnt =%lu vpos=%lu blklen=%d", bytcnt, vpos, blklen);
/* We assume request is within buffer, or just beyond */
txbuf = Txb + (bytcnt & TXBMASK);
if (vpos <= bytcnt)
{
n = fread(txbuf, 1, blklen, in);
vpos += n;
if (n < blklen)
Eofseen = 1;
vfile("zfilbuf: n=%d vpos=%lu Eofseen=%d", n, vpos, Eofseen);
return n;
}
if (vpos >= (bytcnt + blklen))
return blklen;
/* May be a short block if crash recovery etc. */
Eofseen = BEofseen;
return (vpos - bytcnt);
#else
n = fread(txbuf, 1, blklen, in);
if (n < blklen)
Eofseen = 1;
return n;
#endif
}
#ifdef TXBSIZE
/* Replacement for brain damaged fseek function. Returns 0==success */
static int fooseek(FILE * fptr, long pos, int whence)
{
long m, n;
vfile("fooseek: pos =%lu vpos=%lu Canseek=%d", pos, vpos, Canseek);
/* Seek offset < current buffer */
if (pos < (vpos - TXBSIZE + 1024))
{
BEofseen = 0;
if (Canseek > 0)
{
vpos = pos & ~TXBMASK;
if (vpos >= pos)
vpos -= TXBSIZE;
if (fseek(fptr, vpos, 0))
return 1;
} else if (Canseek == 0)
{
if (fseek(fptr, vpos = 0L, 0))
return 1;
} else
return 1;
while (vpos < pos)
{
n = fread(Txb, 1, TXBSIZE, fptr);
vpos += n;
vfile("n=%d vpos=%ld", n, vpos);
if (n < TXBSIZE)
{
BEofseen = 1;
break;
}
}
vfile("vpos=%ld", vpos);
return 0;
}
/* Seek offset > current buffer (Crash Recovery, etc.) */
if (pos > vpos)
{
if (Canseek)
if (fseek(fptr, vpos = (pos & ~TXBMASK), 0))
return 1;
while (vpos <= pos)
{
txbuf = Txb + (vpos & TXBMASK);
m = TXBSIZE - (vpos & TXBMASK);
vfile("m=%ld vpos=%ld", m, vpos);
n = fread(txbuf, 1, m, fptr);
vfile("n=%ld vpos=%ld", n, vpos);
vpos += n;
vfile("bo=%d m=%ld vpos=%ld", txbuf - Txb, m, vpos);
if (n < m)
{
BEofseen = 1;
break;
}
}
return 0;
}
/* Seek offset is within current buffer */
vfile("within buffer: vpos=%ld", vpos);
return 0;
}
#define fseek fooseek
#endif
/* VARARGS1 */
static void vfile( CONST char *form, ... )
{
va_list arg;
char tmp[BUFSIZ];
if ( Verbose > 2 )
{
va_start( arg, form );
vsprintf( tmp, form, arg );
va_end(arg);
USR_fputs(tmp, stderr );
USR_fputs("\n",stderr);
}
}
#ifndef __TOWNS__
static void alrm(void)
{
longjmp(tohere, -1);
}
#endif
/*
* readline(timeout) reads character(s) from file descriptor 0 timeout is in
* tenths of seconds
*/
static int readline(int timeout)
{
register int c;
static char byt[1];
if (setjmp(tohere))
{
zperr("TIMEOUT");
return TIMEOUT;
}
#ifdef __TOWNS__
c = timeout;
if (c < 200 )
c = 200;
if (Verbose > 5)
{
USR_fprintf(stderr, "Timeout=%4d Calling alarm(%4d) ", timeout, c);
}
{
clock_t clk;
clk = H_CLOCK2(0) + c * CLOCKS_PER_SEC / 100;
do
{ if ( (c = RS_chk(RsPort)) > 0 )
{
byt[0] = RS_getc(RsPort);
break;
}
} while ( clk > H_CLOCK2(clk) );
}
#else
c = timeout / 10;
if (c < 2)
c = 2;
if (Verbose > 5)
{
USR_fprintf(stderr, "Timeout=%5d Calling alarm(%d) ", timeout, c);
}
signal(SIGALRM, alrm);
alarm(c);
c = read(0, byt, 1);
alarm(0);
#endif
if (Verbose > 5)
{
if (c < 1)
USR_fprintf(stderr, "timeout!!\n" );
else
USR_fprintf(stderr, "ret %02X\n", byt[0] & 0377);
}
if (c < 1)
return TIMEOUT;
return (byt[0] & 0377);
}
static void flushmo(void)
{
}
static void purgeline(void)
{
#ifndef __TOWNS__
#ifdef USG
ioctl(0, TCFLSH, 0);
#else
lseek(0, 0L, 2);
#endif
#endif
}
/* send cancel string to get the other end to shut up */
static void canit(void)
{
static char canistr[] =
{
24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 0
};
RS_puts(RsPort,canistr);
}
/* Log an error */
/* VARARGS1 */
#ifdef __HIGHC__
static void zperr(char *form, ... )
{
va_list arg;
char tmp[BUFSIZ];
if (Verbose <= 0)
return;
USR_fprintf(stderr, "Retry %d: ", errors);
va_start( arg, form );
vsprintf( tmp, form, arg );
va_end(arg);
USR_fputs(tmp, stderr );
USR_fputs("\n",stderr);
}
#else
static void zperr(char *s, char *p, char *u)
{
if (Verbose <= 0)
return;
USR_fprintf(stderr, "Retry %d: ", errors);
USR_fprintf(stderr, s, p, u);
USR_fprintf(stderr, "\n");
}
#endif
/*
* substr(string, token) searches for token in string s returns pointer to
* token within string if found, NULL otherwise
*/
static char *substr(register char *s, register char *t)
{
register char *ss, *tt;
/* search for first char of token */
for (ss = s; *s; s++)
if (*s == *t)
/* compare token with substring */
for (ss = s, tt = t;;)
{
if (*tt == 0)
return s;
if (*ss++ != *tt++)
break;
}
return NULL;
}
#include "szhelp.c"
/* Send send-init information */
static int getzrxinit(void)
{
register n;
struct stat f;
for (n = 10; --n >= 0;)
{
switch (zgethdr(Rxhdr, 1))
{
case ZCHALLENGE: /* Echo receiver's challenge numbr */
stohdr(Rxpos);
zshhdr(4, ZACK, Txhdr);
continue;
case ZCOMMAND: /* They didn't see out ZRQINIT */
stohdr(0L);
zshhdr(4, ZRQINIT, Txhdr);
continue;
case ZRINIT:
Rxflags = 0377 & Rxhdr[ZF0];
Usevhdrs = Rxhdr[ZF1] & CANVHDR;
Txfcs32 = (Wantfcs32 && (Rxflags & CANFC32));
Zctlesc |= Rxflags & TESCCTL;
Rxbuflen = (0377 & Rxhdr[ZP0]) + ((0377 & Rxhdr[ZP1]) << 8);
if (!(Rxflags & CANFDX))
Txwindow = 0;
vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
#ifndef __TOWNS__
if (!Fromcu)
signal(SIGINT, SIG_IGN);
#else
if (!Fromcu)
{
SIGNAL(SIGINT, SIG_IGN);
CtrlX = FALSE;
}
#endif
#ifdef MODE2OK
mode(2); /* Set cbreak, XON/XOFF, etc. */
/* set XON/XOFF for sb/sz with ZMODEM or YMODEM-g */
#endif
#ifndef READCHECK
#ifndef USG
/* Use 1024 byte frames if no sample/interrupt */
if (Rxbuflen < 32 || Rxbuflen > 1024)
{
Rxbuflen = 1024;
vfile("Rxbuflen=%d", Rxbuflen);
}
#endif
#endif
/* Override to force shorter frame length */
if (Rxbuflen && (Rxbuflen > Tframlen) && (Tframlen >= 32))
Rxbuflen = Tframlen;
if (!Rxbuflen && (Tframlen >= 32) && (Tframlen <= 1024))
Rxbuflen = Tframlen;
vfile("Rxbuflen=%d", Rxbuflen);
/* If using a pipe for testing set lower buf len */
#ifdef __TOWNS__
// Rxbuflen = 1024;
#else
fstat(0, &f);
if ((f.st_mode & S_IFMT) != S_IFCHR)
{
Rxbuflen = 1024;
}
#endif
/*
* If input is not a regular file, force ACK's to prevent
* running beyond the buffer limits
*/
if (!Command)
{
#ifdef _FSTAT_IGN
stat(infile, &f);
#else
fstat(fileno(in), &f);
#endif
if ((f.st_mode & S_IFMT) != S_IFREG)
{
Canseek = -1;
#ifdef TXBSIZE
Txwindow = TXBSIZE - 1024;
Txwspac = TXBSIZE / 4;
#else
return ERROR;
#endif
}
}
/* Set initial subpacket length */
if (blklen < 1024)
{ /* Command line override? */
if (Effbaud > 300)
blklen = 256;
if (Effbaud > 1200)
blklen = 512;
if (Effbaud > 2400)
blklen = 1024;
}
if (Rxbuflen && blklen > Rxbuflen)
blklen = Rxbuflen;
if (blkopt && blklen > blkopt)
blklen = blkopt;
vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
vfile("Txwindow = %u Txwspac = %d", Txwindow, Txwspac);
if (Lztrans == ZTRLE && (Rxflags & CANRLE))
Txfcs32 = 2;
else
Lztrans = 0;
return (sendzsinit());
case ZCAN:
case TIMEOUT:
return ERROR;
case ZRQINIT:
if (Rxhdr[ZF0] == ZCOMMAND)
continue;
default:
zshhdr(4, ZNAK, Txhdr);
continue;
}
}
return ERROR;
}
/* Send send-init information */
static int sendzsinit(void)
{
register c;
if (Myattn[0] == '\0' && (!Zctlesc || (Rxflags & TESCCTL)))
return OK;
errors = 0;
for (;;)
{
stohdr(0L);
#ifdef ALTCANOFF
Txhdr[ALTCOFF] = ALTCANOFF;
#endif
if (Zctlesc)
{
Txhdr[ZF0] |= TESCCTL;
zshhdr(4, ZSINIT, Txhdr);
} else
zsbhdr(4, ZSINIT, Txhdr);
zsdata(Myattn, ZATTNLEN, ZCRCW);
c = zgethdr(Rxhdr, 1);
switch (c)
{
case ZCAN:
return ERROR;
case ZACK:
return OK;
default:
if (++errors > 19)
return ERROR;
continue;
}
}
}
/* Send file name and related info */
static int zsendfile(char *buf, int blen)
{
register c;
register UNSL long crc;
long lastcrcrq = -1;
// char *p;
#ifdef DEBUG
USR_fprintf(stderr,"zsendfile(buf,buflen = %d)\n", blen);
#endif
for (errors = 0; ++errors < 11;)
{
Txhdr[ZF0] = Lzconv; /* file conversion request */
Txhdr[ZF1] = Lzmanag; /* file management request */
if (Lskipnocor)
Txhdr[ZF1] |= ZMSKNOLOC;
Txhdr[ZF2] = Lztrans; /* file transport request */
Txhdr[ZF3] = 0;
zsbhdr(4, ZFILE, Txhdr);
zsdata(buf, blen, ZCRCW);
again:
c = zgethdr(Rxhdr, 1);
switch (c)
{
case ZRINIT:
while ((c = readline(50)) > 0)
{
if ( c == ZPAD )
goto again;
}
continue;
case ZCAN:
case TIMEOUT:
case ZABORT:
case ZFIN:
sprintf(endmsg, "Got %s on pathname", frametypes[c + FTOFFSET]);
return ERROR;
default:
sprintf(endmsg, "Got %d frame type on pathname", c);
return ERROR;
case ERROR:
case ZNAK:
continue;
case ZCRC:
if (Rxpos != lastcrcrq)
{
lastcrcrq = Rxpos;
crc = 0xFFFFFFFFL;
if (Canseek >= 0)
{
fseek(in, 0L, 0);
while ( ((c = fgetc(in)) != EOF) && --lastcrcrq )
crc = UPDC32(c, crc);
crc = ~crc;
clearerr(in); /* Clear possible EOF */
lastcrcrq = Rxpos;
}
}
stohdr(crc);
zsbhdr(4, ZCRC, Txhdr);
goto again;
case ZFERR:
case ZSKIP:
sprintf(endmsg, "File skipped by receiver request");
FM_fclose(in);
return c;
case ZRPOS:
/*
* Suppress zcrcw request otherwise triggered by
* lastyunc==bytcnt
*/
if (fseek(in, Rxpos, 0))
return ERROR;
Lastsync = (long)(bytcnt = Txpos = Lrxpos = Rxpos) - 1l;
return zsendfdata();
}
}
}
/* Send the data in the file */
static int zsendfdata(void)
{
register c, e, n;
register newcnt;
register long tcount = 0;
int junkcount; /* Counts garbage chars received by TX */
static int tleft = 6; /* Counter for test mode */
#ifdef DEBUG
USR_fprintf(stderr,"zsenfdata \n");
#endif
junkcount = 0;
Beenhereb4 = FALSE;
somemore:
if ( setjmp(intrjmp) )
{
waitack:
junkcount = 0;
c = getinsync(0);
gotack:
switch (c)
{
default:
case ZCAN:
FM_fclose(in);
return ERROR;
case ZSKIP:
FM_fclose(in);
return c;
case ZACK:
case ZRPOS:
break;
case ZRINIT:
FM_fclose(in); in = NULL;
return OK;
}
#ifdef READCHECK
/*
* If the reverse channel can be tested for data, this logic may be
* used to detect error packets sent by the receiver, in place of
* setjmp/longjmp rdchk(fd) returns non 0 if a character is available
*/
while (rdchk(0))
{
#ifdef EATSIT
switch (checked)
#else
switch (readline(1))
#endif
{
case CAN:
case ZPAD:
c = getinsync(1);
goto gotack;
case XOFF: /* Wait a while for an XON */
case XOFF | 0200:
readline(100);
}
}
#endif
}
#ifndef __TOWNS__
if (!Fromcu)
signal(SIGINT, onintr);
#else
if (!Fromcu)
{
CtrlX = TRUE;
SIGNAL(SIGINT, onintr);
}
#endif
newcnt = Rxbuflen;
Txwcnt = 0;
stohdr(Txpos);
zsbhdr(4, ZDATA, Txhdr);
/*
* Special testing mode. This should force receiver to Attn,ZRPOS many
* times. Each time the signal should be caught, causing the file to be
* started over from the beginning.
*/
if (Test)
{
if (--tleft)
while (tcount < 20000)
{
RS_puts(RsPort,qbf);
tcount += strlen(qbf);
#ifdef READCHECK
while (rdchk(0))
{
#ifdef EATSIT
switch (checked)
#else
switch (readline(1))
#endif
{
case CAN:
case ZPAD:
#ifndef __TOWNS__
# ifdef TCFLSH
ioctl(0, TCFLSH, 1);
# endif
#endif
goto waitack;
case XOFF: /* Wait for XON */
case XOFF | 0200:
readline(100);
}
}
#endif
}
#ifndef __TOWNS__
signal(SIGINT, SIG_IGN);
#else
SIGNAL(SIGINT, SIG_IGN);
CtrlX = FALSE;
#endif
canit();
#ifdef __TOWNS__
{
clock_t clk;
clk = H_CLOCK2(0) + 3 * CLOCKS_PER_SEC;
while ( clk > H_CLOCK2(clk) )
;
}
#else
sleep(3);
#endif
purgeline();
mode(0); /* restore original tty mode */
USR_printf("\nsz: Tcount = %ld\n", tcount);
if (tleft)
{
USR_printf("ERROR: Interrupts Not Caught\n");
EXIT(1);
}
EXIT(0);
}
do
{
n = zfilbuf();
if (Eofseen)
e = ZCRCE;
else if (junkcount > 3)
e = ZCRCW;
else if (bytcnt == Lastsync)
e = ZCRCW;
else if (Rxbuflen && (newcnt -= n) <= 0)
e = ZCRCW;
else if (Txwindow && (Txwcnt += n) >= Txwspac)
{
Txwcnt = 0;
e = ZCRCQ;
} else
e = ZCRCG;
if (Verbose > 1)
{
USR_fprintf(stderr, "\r%7ld ZMODEM%s ",
Txpos, Crc32t ? " CRC-32" : "");
}
zsdata(txbuf, n, e);
bytcnt = Txpos += n;
if (e == ZCRCW)
goto waitack;
#ifdef READCHECK
/*
* If the reverse channel can be tested for data, this logic may be
* used to detect error packets sent by the receiver, in place of
* setjmp/longjmp rdchk(fd) returns non 0 if a character is available
*/
while ( rdchk(0) )
{
#ifdef EATSIT
switch (checked)
#else
switch ( readline(1) )
#endif
{
case CAN:
case ZPAD:
c = getinsync(1);
if (c == ZACK)
break;
#ifndef __TOWNS__
# ifdef TCFLSH
ioctl(0, TCFLSH, 1);
# endif
#endif
/* zcrce - dinna wanna starta ping-pong game */
zsdata(txbuf, 0, ZCRCE);
goto gotack;
case XOFF: /* Wait a while for an XON */
case XOFF | 0200:
readline(100);
default:
++junkcount;
}
}
#endif /* READCHECK */
if (Txwindow)
{
while ((tcount = (Txpos - Lrxpos)) >= Txwindow)
{
vfile("%ld window >= %u", tcount, Txwindow);
if (e != ZCRCQ)
zsdata(txbuf, 0, e = ZCRCQ);
c = getinsync(1);
if (c != ZACK)
{
#ifndef __TOWNS__
#ifdef TCFLSH
ioctl(0, TCFLSH, 1);
#endif
#endif
zsdata(txbuf, 0, ZCRCE);
goto gotack;
}
}
vfile("window = %ld", tcount);
}
} while (!Eofseen);
#ifndef __TOWNS__
if (!Fromcu)
signal(SIGINT, SIG_IGN);
#else
if (!Fromcu)
{
SIGNAL(SIGINT, SIG_IGN);
CtrlX = FALSE;
}
#endif
for (;;)
{
stohdr(Txpos);
zsbhdr(4, ZEOF, Txhdr);
switch (getinsync(0))
{
case ZACK:
continue;
case ZRPOS:
goto somemore;
case ZRINIT:
FM_fclose(in); in = NULL;
return OK;
case ZSKIP:
FM_fclose(in); in = NULL;
sprintf(endmsg, "File skipped by receiver request");
return c;
default:
sprintf(endmsg, "Got %d trying to send end of file", c);
FM_fclose(in); in = NULL;
return ERROR;
}
}
}
/*
* Respond to receiver's complaint, get back in sync with receiver
*/
static int getinsync(int flag)
{
register c;
#ifdef DEBUG
USR_fprintf(stderr,"getinsync(int %d)\n", flag );
#endif
for (;;)
{
if (Test)
{
RS_puts(RsPort,"\r\n\n\n***** Signal Caught *****\r\n");
Rxpos = 0;
c = ZRPOS;
} else
c = zgethdr(Rxhdr, 0);
switch (c)
{
case ZCAN:
case ZABORT:
case ZFIN:
case TIMEOUT:
sprintf(endmsg, "Got %s sending data", frametypes[c + FTOFFSET]);
return ERROR;
case ZRPOS:
/* ************************************* */
/* If sending to a buffered modem, you */
/* might send a break at this point to */
/* dump the modem's buffer. */
clearerr(in); /* In case file EOF seen */
if (fseek(in, Rxpos, 0))
return ERROR;
Eofseen = 0;
bytcnt = Lrxpos = Txpos = Rxpos;
if (Lastsync == Rxpos)
{
#ifdef DEBUG
if (++Beenhereb4 > 32)
#else
if (++Beenhereb4 > 12)
#endif
{
sprintf(endmsg, "Can't send block");
return ERROR;
}
if (Beenhereb4 > 4)
{
if (blklen > 32)
blklen /= 2;
}
}
Lastsync = Rxpos;
return c;
case ZACK:
Lrxpos = Rxpos;
if (flag || Txpos == Rxpos)
return ZACK;
continue;
case ZRINIT:
return c;
case ZSKIP:
sprintf(endmsg, "File skipped by receiver request");
return c;
case ERROR:
default:
zsbhdr(4, ZNAK, Txhdr);
continue;
}
}
}
/* Say "bibi" to the receiver, try to do it cleanly */
static void saybibi(void)
{
for (;;)
{
stohdr(0L); /* CAF Was zsbhdr - minor change */
zshhdr(4, ZFIN, Txhdr); /* to make debugging easier */
switch (zgethdr(Rxhdr, 0))
{
case ZFIN:
sendline('O');
sendline('O');
flushmo();
case ZCAN:
case TIMEOUT:
return;
}
}
}
/* Local screen character display function */
static void bttyout(int c)
{
if (Verbose)
USR_fputc(c, stderr);
}
/* Send command and related info */
static int zsendcmd(char *buf, int blen)
{
register c;
long cmdnum;
#ifdef DEBUG
vfile("zsendcmd()");
#endif
#ifdef __HIGHC__
cmdnum = _getpid();
#else
cmdnum = getpid();
#endif
errors = 0;
for (;;)
{
stohdr(cmdnum);
Txhdr[ZF0] = Cmdack1;
zsbhdr(4, ZCOMMAND, Txhdr);
zsdata(buf, blen, ZCRCW);
listen:
Rxtimeout = 100; /* Ten second wait for resp. */
Usevhdrs = 0; /* Allow rx to send fixed len headers */
c = zgethdr(Rxhdr, 1);
switch (c)
{
case ZRINIT:
goto listen; /* CAF 8-21-87 */
case ERROR:
case GCOUNT:
case TIMEOUT:
if (++errors > Cmdtries)
return ERROR;
continue;
case ZCAN:
case ZABORT:
case ZFIN:
case ZSKIP:
case ZRPOS:
return ERROR;
default:
if (++errors > 20)
return ERROR;
continue;
case ZCOMPL:
Exitcode = Rxpos;
saybibi();
return OK;
case ZRQINIT:
vfile("******** RZ *******");
#ifndef __TOWNS__
system("rz");
#endif
vfile("******** SZ *******");
goto listen;
}
}
}
/*
* If called as sb use YMODEM protocol
*/
static void chkinvok(char *s)
{
register char *p;
p = s;
while (*p == '-')
s = ++p;
while (*p)
if (*p++ == '/')
s = p;
if (*s == 'v')
{
Verbose = 1;
++s;
}
Progname = s;
if (s[0] == 's' && s[1] == 'b')
{
Nozmodem = TRUE;
blklen = 1024;
}
if (s[0] == 's' && s[1] == 'x')
{
Modem2 = TRUE;
}
}
static void countem(int argc, register char **argv)
{
struct stat f;
Totalleft = 0;
Filesleft = 0;
for ( ; --argc >= 0; ++argv)
{
f.st_size = -1;
if (Verbose > 2)
{
USR_fprintf(stderr, "\nCountem: %03d %s ", argc, *argv);
}
#ifdef __TOWNS__
if (_access(*argv, 3) >= 0 && stat(*argv, &f) >= 0)
#else
if ( _access(*argv, 04) >= 0 && stat(*argv, &f) >= 0)
#endif
{
#ifndef __TOWNS__
register c;
c = f.st_mode & S_IFMT;
if (c != S_IFDIR && c != S_IFBLK)
{
#endif
++Filesleft;
Totalleft += f.st_size;
#ifndef __TOWNS__
}
#endif
}
if ( Verbose > 2 )
USR_fprintf(stderr, " %ld", f.st_size);
}
if ( Verbose > 2 )
USR_fprintf(stderr, "\ncountem: Total %d %ld\n",
Filesleft, Totalleft);
}
static void chartest(int m)
{
register n;
mode(m);
RS_printf(RsPort,"\r\n\nCharacter Transparency Test Mode %d\r\n", m);
RS_printf(RsPort,"If Pro-YAM/ZCOMM is not displaying ^M hit ALT-V NOW.\r\n");
RS_printf(RsPort,"Hit Enter.\021");
readline(500);
for (n = 0; n < 256; ++n)
{
if (!(n % 8))
RS_puts(RsPort,"\r\n");
RS_printf(RsPort,"%02x ", n);
sendline(n);
flushmo();
RS_puts(RsPort," ");
if (n == 127)
{
RS_puts(RsPort,"Hit Enter.\021");
readline(500);
RS_puts(RsPort,"\r\n");
}
}
RS_puts(RsPort,"\021\r\nEnter Characters, echo is in hex.\r\n");
RS_puts(RsPort,"Hit SPACE or pause 40 seconds for exit.\r\n");
while (n != TIMEOUT && n != ' ')
{
n = readline(400);
RS_printf(RsPort,"%02x\r\n", n);
}
RS_printf(RsPort,"\r\nMode %d character transparency test ends.\r\n", m);
}
/* End of sz.c */